/**
 * grayrabbit Inc.
 * Copyright (c) 2011-2012 All Rights Reserved.
 */
package com.grayrabbit.slacker.gengerate;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.grayrabbit.slacker.config.GenerateConfig;
import com.grayrabbit.slacker.constant.PropertyConsant;
import com.grayrabbit.slacker.interfaces.CodeGenerate;
import com.grayrabbit.slacker.utils.TemplateProcessUtils;

/**
 * 映射实体类生成工具类
 * 
 * @author liyd
 * @version $Id: EntityGenerate.java, v 0.1 2012-5-8 下午7:00:53 liyd Exp $
 */
public class EntityGenerate extends NormalGenerate implements CodeGenerate {

    /** 
     * @see com.grayrabbit.slacker.interfaces.CodeGenerate#generate(com.grayrabbit.slacker.config.GenerateConfig, java.util.Map)
     */
    public void generate(GenerateConfig generateConfig, Map<String, String> modelMap) {

        //常规数据初始化
        super.normalDataInit(generateConfig);

        //需要导入的类集合
        Set<String> importClassSet = new HashSet<String>();

        //属性
        StringBuilder sbProperties = new StringBuilder();

        //get和set方法
        StringBuilder getterAndSetter = new StringBuilder();

        //根据属性生成
        for (String[] column : generateConfig.getColumns()) {

            //需要导入的类,忽略java.lang包
            if (!column[0].startsWith("java.lang")) {
                importClassSet.add(column[0]);
            }
            //得到java属性类型，非完全类名
            int index = column[0].lastIndexOf(".") + 1;
            String proType = column[0].substring(index);

            //属性名称
            String propertyName = TemplateProcessUtils.getPropertyName(column[1]);

            //属性备注
            String propertyComment = column[2];

            //属性生成
            sbProperties.append(generateProperties(generateConfig, proType, propertyName,
                propertyComment, column[1]));

            //get set方法生成
            getterAndSetter.append(generateGetAndSet(generateConfig, proType, propertyName));
        }

        modelMap.put("package", this.PACKAGE);

        modelMap.put("tableName", this.TABLE_NAME);

        modelMap.put("className", this.getClassName(TARGET_QUALIFIED_CLASS_NAME));

        modelMap.put("gmtCreate", this.GMT_CREATE);

        modelMap.put("import", getImportClass(importClassSet));

        modelMap.put("serialVersionUID", getSerialVersionUID());

        modelMap.put("properties", sbProperties.toString());

        modelMap.put("getterAndSetter", getterAndSetter.toString());

    }

    /**
     * 获取需要导入的类
     * 
     * @param importClassSet
     * @return
     */
    private String getImportClass(Set<String> importClassSet) {

        StringBuilder sbImportClass = new StringBuilder();

        for (String importClass : importClassSet) {

            sbImportClass.append("import " + importClass + ";");
            sbImportClass.append("\r\n");

        }

        return sbImportClass.toString();
    }

    /**
     * 生成属性模板文件
     * 
     * @param propertyType
     * @param propertyName
     * @param columnName
     * @return
     */
    private String generateProperties(GenerateConfig generateConfig, String propertyType,
                                      String propertyName, String propertyComment, String columnName) {

        //属性模板文件
        String proVm = TemplateProcessUtils.getTemplate(generateConfig.getProperties()
            .get(PropertyConsant.TEMPLATE).getChildProperties().get("propertyTemplate").getValue());

        proVm = proVm.replaceAll("\\$\\{propertyType\\}", propertyType);
        proVm = proVm.replaceAll("\\$\\{propertyName\\}", propertyName);
        proVm = proVm.replaceAll("\\$\\{propertyComment\\}", propertyComment);
        proVm = proVm.replaceAll("\\$\\{columnName\\}", columnName);

        return proVm;
    }

    /**
     * 生成get和set方法模板文件
     * 
     * @param propertyType
     * @param propertyName
     * @return
     */
    private String generateGetAndSet(GenerateConfig generateConfig, String propertyType,
                                     String propertyName) {

        //get set方法模板文件
        String getAndsetVm = TemplateProcessUtils
            .getTemplate(generateConfig.getProperties().get(PropertyConsant.TEMPLATE)
                .getChildProperties().get("getAndsetTemplate").getValue());
        getAndsetVm = getAndsetVm.replaceAll("\\$\\{propertyType\\}", propertyType);
        getAndsetVm = getAndsetVm.replaceAll("\\$\\{propertyName\\}", propertyName);
        getAndsetVm = getAndsetVm.replaceAll("\\$\\{methodPropertyName\\}",
            TemplateProcessUtils.convertFirstUpper(propertyName));

        return getAndsetVm;
    }

}
